import tkinter as tk
from tkinter import messagebox
import re
import sqlite3

success = 'user_data.db'

MAX_USERNAME_LENGTH = 20  # 最大用户名长度限制
MAX_PASSWORD_LENGTH = 20  # 最大密码长度限制
MIN_USERNAME_LENGTH = 6  # 最小用户名长度限制
MIN_PASSWORD_LENGTH = 6  # 最小密码长度限制

def create_users_table(conn):
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS users
                    (id INTEGER PRIMARY KEY AUTOINCREMENT,
                    username TEXT NOT NULL,
                    password TEXT NOT NULL)''')
    conn.commit()

def read_users_from_db(conn):
    users = {}
    try:
        cursor = conn.cursor()
        cursor.execute('SELECT username, password FROM users')
        rows = cursor.fetchall()
        for row in rows:
            users[row[0]] = row[1]
    except Exception as e:
        print(f"Error reading users from DB: {e}")
    return users

def add_user_to_db(conn, username, password):
    try:
        cursor = conn.cursor()
        cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, password))
        conn.commit()
        print("User added to DB successfully.")
    except Exception as e:
        print(f"Error adding user to DB: {e}")

def is_valid_input(input_str):
    # 使用正则表达式检查输入是否只包含数字和字母
    return bool(re.match("^[a-zA-Z0-9]+$", input_str))

def sign_in_f():
    user_si_name = nameval.get()
    user_si_pass = passwordval.get()

    conn = sqlite3.connect(success)
    users = read_users_from_db(conn)

    if user_si_name in users and users[user_si_name] == user_si_pass:
        messagebox.showinfo("登录", "登录成功")
    else:
        messagebox.showerror("登录错误", "用户名或密码无效")

def sign_up_f():
    def su_conf_b():
        su_username = su_name_val.get()
        su_userpass = su_pass_val.get()
        su_usercpass = su_cpass_val.get()

        conn = sqlite3.connect(success)

        # 检测用户名和密码是否包含非法字符
        if not is_valid_input(su_username) or not is_valid_input(su_userpass):
            messagebox.showerror("注册错误", "用户名或密码只能包含数字和字母，请重试。")
            return

        # 检查用户名和密码长度是否符合要求
        if len(su_username) > MAX_USERNAME_LENGTH or len(su_userpass) > MAX_PASSWORD_LENGTH:
            messagebox.showerror("注册错误", f"用户名和密码长度不能超过{MAX_USERNAME_LENGTH}个字符。")
            return

        if len(su_username) < MIN_USERNAME_LENGTH or len(su_userpass) < MIN_PASSWORD_LENGTH:
            messagebox.showerror("注册错误", f"用户名和密码长度不能低于{MIN_USERNAME_LENGTH}个字符。")
            return

        if su_userpass == su_usercpass:
            add_user_to_db(conn, su_username, su_userpass)
            messagebox.showinfo("注册", "注册成功，请登录。")
            singn_up_w.destroy()
        else:
            messagebox.showerror("注册错误", "密码不匹配，请重试。")

    singn_up_w = tk.Toplevel()
    singn_up_w.title("用户注册")
    singn_up_w.geometry("400x300")

    su_name_lable = tk.Label(singn_up_w, text="用户名:", font=(12))
    su_pass_lable = tk.Label(singn_up_w, text="密码:", font=(12))
    su_cpass_lable = tk.Label(singn_up_w, text="确认密码:", font=(12))
    su_name_lable.place(x=60, y=80)
    su_pass_lable.place(x=60, y=120)
    su_cpass_lable.place(x=60, y=160)

    su_name_val = tk.StringVar()
    su_pass_val = tk.StringVar()
    su_cpass_val = tk.StringVar()
    su_name_entry = tk.Entry(singn_up_w, textvariable=su_name_val, width=20, font=(12))
    su_pass_entry = tk.Entry(singn_up_w, textvariable=su_pass_val, width=20, show="*", font=(12))
    su_cpass_entry = tk.Entry(singn_up_w, textvariable=su_cpass_val, width=20, show="*", font=(12))
    su_name_entry.place(x=180, y=80)
    su_pass_entry.place(x=180, y=120)
    su_cpass_entry.place(x=180, y=160)

    su_confirm_button = tk.Button(singn_up_w, text="注册", command=su_conf_b)
    su_confirm_button.place(x=120, y=200)

    # 添加取消按钮
    su_cancel_button = tk.Button(singn_up_w, text="取消", command=singn_up_w.destroy)
    su_cancel_button.place(x=220, y=200)

window = tk.Tk()
window.title("手写数字识别系统登陆界面")
window.geometry("400x300")

name_lable = tk.Label(window, text="用户名:", font=(15))
password_lable = tk.Label(window, text="密码:", font=(15))
name_lable.place(x=90, y=90)
password_lable.place(x=90, y=140)

nameval = tk.StringVar()
passwordval = tk.StringVar()
name_entry = tk.Entry(window, textvariable=nameval, font=(12))
password_entry = tk.Entry(window, textvariable=passwordval, show="*", font=(12))
name_entry.place(x=180, y=90)
password_entry.place(x=180, y=140)

sign_in_button = tk.Button(window, text="登录", command=sign_in_f)
sign_up_button = tk.Button(window, text="注册", command=sign_up_f)
sign_in_button.place(x=120, y=200)
sign_up_button.place(x=220, y=200)

# 连接数据库并创建用户表
conn = sqlite3.connect(success)
create_users_table(conn)

window.mainloop()
